﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using QQTools.Core.Enums.SendGroupMessage;
using QQTools.Data.Enums.AddGroup;
using QQTools.Data.Enums.SendGroupMessage;
using QQTools.Data.Models;
using QQTools.Data.Models.SendGroupMsg;
using QQTools.Data.Plus;
using QQTools.Data.Repositories.ForwardGroupMessage;
using QQTools.Data.Repositories.SendGroupMessage;
using QQTools.Logging;
using QQTools.Services.Automation;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskBand;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace QQTools.Services
{
    public class SendGroupMsgServices
    {
        public static SendGroupMsgQQRepository _sendGroupMsgQQRepository;
        public static SendGroupMsgRepository _sendGroupMsgRepository;
        private MainForm _form;

        public SendGroupMsgServices(SendGroupMsgQQRepository sendGroupMsgQQRepository, SendGroupMsgRepository sendGroupMsgRepository, MainForm form)
        {
            _sendGroupMsgQQRepository = sendGroupMsgQQRepository;
            _sendGroupMsgRepository = sendGroupMsgRepository;

            _form = form;
        }

        public async Task Start(List<QQModel> qqList, SendGroupMsgType msgType, string picPath, int sendIntervalStart, int sendIntervalEnd, int batchRecipientCount, int accountTotalSend, CancellationToken token)
        {
            // 重置所有任务的消息类型为 msgType
            _sendGroupMsgRepository.ResetMsgTypeAsync(msgType);
            // 1. 获取所有任务QQ账号
            List<SendGroupMsgQQModel> sendGroupMsgQQModels = await _sendGroupMsgQQRepository.GetAllAsync();

            // 获取该QQ的所有群, 并且高亮第一个群号
            _form.UpdateListViewSendGroupMsg(qq: sendGroupMsgQQModels.FirstOrDefault()?.QQ);
            string msg;

            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    LogManager.Info("[群发] 任务已取消3");
                    break;
                }
                // 如果所有任务QQ的群没有需要发送的群时,任务结束
                int unusedCount = await _sendGroupMsgRepository.GetCountByStatusAsync(SendGroupMsgStatus.NotStarted);
                if (unusedCount <= 0)
                {
                    msg = "[群发] 所有群聊都已发送完毕, 任务已完成";
                    _form.UpdateStatusStrip(msg);
                    LogManager.Info(msg);
                    break;
                }
                sendGroupMsgQQModels = await _sendGroupMsgQQRepository.GetAllAsync();
                // 2.如果所有任务QQ的发送数量达到预设, 任务结束
                int finishedCount = 0;
                foreach (var qqItem in sendGroupMsgQQModels)
                {
                    if (token.IsCancellationRequested)
                    {
                        LogManager.Info("[群发] 任务已取消4");
                        break;
                    }
                    if (accountTotalSend > 0 && qqItem.SendCount >= accountTotalSend)
                    {// 发送数量达标
                        msg = $"[群发] QQ:{qqItem.QQ} 进度:{qqItem.SendCount}/{accountTotalSend} 任务已完成";
                        _form.UpdateStatusStrip(msg);
                        LogManager.Info(msg);
                        finishedCount++;
                    }
                    else
                    { // 数量不够走这里
                        unusedCount = await _sendGroupMsgRepository.GetCountByQQAndStatusAsync(qqItem.QQ, SendGroupMsgStatus.NotStarted);
                        if (unusedCount <= 0) // 或没有需要发送的群, 也算达标
                        {
                            finishedCount++;
                            msg = $"[群发] QQ:{qqItem.QQ} 名下所有群聊都已发送完毕, 任务已完成";
                            _form.UpdateStatusStrip(msg);
                            LogManager.Info(msg);
                        }
                        else
                        {   // 数量不够, 且还有未发送的群聊, 走这里判断是否离线
                            int pid = qqList.FirstOrDefault(q => q.QQ == qqItem.QQ)?.LastPid ?? 0;
                            bool isOnline = QQPlus.IsOnline(qqItem.QQ, pid);
                            // QQ离也算达标
                            if (isOnline == false)
                            {
                                finishedCount++;
                                msg = $"[群发] QQ:{qqItem.QQ} 已离线, 任务已完成";
                                _form.UpdateStatusStrip(msg);
                                LogManager.Info(msg);
                            }
                            // 加点延迟,防止QQ崩溃
                            await Task.Delay(200);
                        }

                    }
                }
                if (finishedCount >= sendGroupMsgQQModels.Count)
                {
                    msg = "[群发] 所有任务已完成";
                    _form.UpdateStatusStrip(msg);
                    LogManager.Info(msg);
                    return;
                }
                // 记录是不是 QQ 离线 结束
                bool qqOfflineflag = false;
                // 1.遍历QQ列表
                foreach (var qqItem in sendGroupMsgQQModels)
                {
                    if (token.IsCancellationRequested)
                    {
                        LogManager.Info("[群发] 任务已取消2");
                        break;
                    }
                    string qq = qqItem.QQ;

                    // UI更新任务:QQ列表, 并将当前QQ高亮
                    _form.UpdateListViewSendGroupMsgQQ(qq: qq);


                    // 从qqList 获取对应qq的pid
                    int pid = qqList.FirstOrDefault(q => q.QQ == qq)?.LastPid ?? 0;
                    if (pid == 0)
                    {
                        LogManager.Error($"[群发] 未找到QQ:{qq} 的pid");
                        continue;
                    }

                    //bool isOnline = QQPlus.IsOnline(qqItem.QQ, pid);
                    //// QQ离也算达标
                    //if (isOnline == false)
                    //{
                    //    msg = $"[群发] QQ:{qqItem.QQ} 已离线, 跳过";
                    //    _form.UpdateStatusStrip(msg);
                    //    continue;
                    //}

                    // 判断群发数量是否达标
                    // 判断群发数量是否超出预设
                    if (accountTotalSend > 0 && qqItem.SendCount >= accountTotalSend)
                    {
                        // 保存QQ列表进度
                        await _sendGroupMsgQQRepository.UpdateAsync(qqItem);
                        msg = $"[群发] QQ:{qqItem.QQ} 进度:{qqItem.SendCount}/{accountTotalSend} 任务已完成";
                        _form.UpdateStatusStrip(msg);
                        LogManager.Info(msg);
                        continue;
                    }


                    // 从数据库中获取当前QQ对应的群列表
                    List<SendGroupMsgModel> sendGroupMsgModelList = await _sendGroupMsgRepository.GetByQQAsync(qq);

                    // 取一条任务
                    SendGroupMsgModel groupInfo = await _sendGroupMsgRepository.GetAndLockNextSendGroupAsync(qq);
                    if (groupInfo == null)
                    {
                        msg = $"[群发] {qq} 没有需要发送的群 切换下一个QQ";
                        _form.UpdateStatusStrip(msg);
                        LogManager.Info(msg);
                        continue;
                    }

                    // 获取总任务数
                    int totalGroup = await _sendGroupMsgRepository.GetCountByQQAsync(qq);
                    // 默认当前群发送次数0
                    //int currentGroupSendCount = 0;

                    if (token.IsCancellationRequested)
                    {
                        LogManager.Info("[群发] 任务已取消1");
                        break;
                    }
                    msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 开始发送, 类型:{msgType.ToString()} ";
                    LogManager.Info(msg);
                    // UI更新:状态栏
                    _form.UpdateStatusStrip(msg);
                    // UI更新任务:群列表状态,并将当前群号高亮
                    _form.UpdateListViewSendGroupMsg(groupInfo);
                    // 如果发送次数大于重试次数则跳过
                    if (groupInfo.SendCount > groupInfo.RetryCount)
                    {
                        msg = $"[群发] 发送失败 QQ:{qq} 的群:{groupInfo.GroupNumber} 已经重试:{groupInfo.SendCount}/{groupInfo.RetryCount}次, 跳过";
                        _form.UpdateStatusStrip(msg);
                        LogManager.Error(msg);
                        // 更新任务状态
                        await _sendGroupMsgRepository.UpdateStatusByQQAndGroupNumberAsync(groupInfo.QQ, groupInfo.GroupNumber, SendGroupMsgStatus.Failed);
                        continue;
                    }
                    // 封裝消息
                    GroupMsgModel groupMsgModel = new GroupMsgModel
                    {
                        QQ = qq,
                        GroupNumber = groupInfo.GroupNumber,
                        Text = groupInfo.MessageContent,
                        MsgType = msgType,
                        PicPath = picPath
                    };

                    // 模拟群发消息
                    SendGroupMsgAuto sendGroupMsgAuto = new SendGroupMsgAuto(pid);
                    // 默认发送失败
                    SendGroupMsgResult result = SendGroupMsgResult.Faild;

                    for (int attempt = 1; attempt <= 3; attempt++)
                    {
                        if (token.IsCancellationRequested)
                        {
                            LogManager.Info("[群发] 任务已取消2220");
                            break;
                        }
                        // 实际发送消息

                        (result, qqItem.ResourceIndex) = await sendGroupMsgAuto.SendGroupMsg(qq, groupInfo.GroupNumber, groupMsgModel, token, attempt);
                        if (result == SendGroupMsgResult.Success)
                        {
                            break;
                        }
                        else if (result == SendGroupMsgResult.GroupBlockedOrNotAdded) // 出现安全窗口或群未添加
                        {
                            break;
                        }
                        else if (result == SendGroupMsgResult.QQOffline) // 出现离线
                        {
                            break;
                        }
                        else if (result == SendGroupMsgResult.GroupMute) // 出现禁言
                        {
                            break;
                        }
                        else if (result == SendGroupMsgResult.ResourceNotFound)
                        {
                            msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 的资源不存在, 第{attempt}次发送失败, 重试中...";
                            // 资源没找到, 重置资源下标
                            qqItem.ResourceIndex = 1;
                            await _sendGroupMsgQQRepository.UpdateAsync(qqItem);
                        }
                        else
                        {
                            msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 下标:{qqItem.ResourceIndex} 第{attempt}次发送失败, 重试中...";

                        }
                        LogManager.Error(msg);
                        _form.UpdateStatusStrip(msg);
                    }

                    if (result == SendGroupMsgResult.Success)
                    {
                        // 资源索引加1
                        qqItem.ResourceIndex += 1;
                        // 群发成功,QQ成功次数+1
                        qqItem.SendCount++;
                        // 重置当前群发送次数
                        groupInfo.SendCount = 0;
                        groupInfo.Status = SendGroupMsgStatus.Success;
                        // 更新群发任务状态:成功
                        await _sendGroupMsgRepository.UpdateStatusByQQAndGroupNumberAsync(groupInfo.QQ, groupInfo.GroupNumber, SendGroupMsgStatus.Success);
                        msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 下标:{qqItem.ResourceIndex} 发送成功, 进度:{qqItem.SendCount}/{accountTotalSend}";
                    }
                    else
                    {
                        qqItem.FailedCount++;
                        groupInfo.SendCount++;
                        groupInfo.Status = SendGroupMsgStatus.Failed;
                        // 更新群发任务状态:失败
                        await _sendGroupMsgRepository.UpdateStatusByQQAndGroupNumberAsync(groupInfo.QQ, groupInfo.GroupNumber, SendGroupMsgStatus.Failed);
                        if (result == SendGroupMsgResult.GroupBlockedOrNotAdded)
                        {
                            msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 群未添加或已被封禁";
                        }
                        else if (result == SendGroupMsgResult.GroupMute)
                        {
                            msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 群已禁言";
                        }
                        else if (result == SendGroupMsgResult.QQOffline)
                        {
                            msg = $"[群发:QQ离线]] QQ:{qq}  群:{groupInfo.GroupNumber} 分类:{msgType.ToString()}";
                            // 标记为离线结束
                            qqOfflineflag = true;
                        }

                        else
                        {
                            msg = $"[群发] QQ:{qq} 群:{groupInfo.GroupNumber} 分类:{msgType.ToString()} 下标:{qqItem.ResourceIndex} 发送失败，达到最大重试次数！, 进度:{qqItem.SendCount}/{accountTotalSend}";
                        }
                    }

                    // 保存QQ列表进度
                    await _sendGroupMsgQQRepository.UpdateAsync(qqItem);
                    // 保存群列表进度
                    await _sendGroupMsgRepository.UpdateAsync(groupInfo);

                    // UI更新任务:QQ列表状态, 并将当前QQ高亮
                    _form.UpdateListViewSendGroupMsgQQ(qq: qq);
                    // UI更新任务:群列表状态,并将当前群号高亮
                    _form.UpdateListViewSendGroupMsg(groupInfo);

                    if (qqOfflineflag)
                    { // QQ离线结束
                        msg = $"{msg} QQ已离线, 任务已完成, 继续下一个QQ";
                        _form.UpdateStatusStrip(msg);
                        LogManager.Info(msg);
                        continue;

                    }
                    int interval = new Random().Next(sendIntervalStart, sendIntervalEnd + 1);
                    LogManager.Info($"{msg} 距离发送还剩: {interval} 秒");
                    await _form.StartCountdown($"{msg} 距离发送还剩:", interval, token, $"{msg} 任务停止", null);
                }
            }

        }
    }
}
